using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using Yoozoo.Libs;
using Yoozoo.Managers.NetworkV2.Client;
using Yoozoo.Managers.NetworkV2.Core;
using Yoozoo.Managers.NetworkV2.DataStruct;
using Yoozoo.Managers.NetworkV2.Helpers;

namespace Yoozoo.Framework.Network.Helpers
{
    public class GTAPacketSerializerHelper : IPacketSerializedHelper
    {
        /// <summary>
        /// 发包包头部长度
        /// </summary>
        private const int CS_PACKAGE_HEAD_LENGTH = 6;

        /// <summary>
        /// 包索引
        /// </summary>
        public static volatile int msgIndex = 0;

        
        private bool IsAESEncrypt(IPacket packet)
        {
            var packetBase = packet as BasicPacket;
            if (packetBase!=null && packetBase.customData!=null)
                return (bool)packetBase.customData;
            return false;
        }

        public bool SerializePacketHandler(IPacket packet, Stream destination)
        {
            if(packet.rawData == null)
            {
                return false;
            }
            
            m_SerializeCachedStream.SetLength(m_SerializeCachedStream.Capacity); // 此行防止 Array.Copy 的数据无法写入
            m_SerializeCachedStream.Position = 0L;
            
            // ReSharper disable once LocalVariableHidesMember
            ushort msgIndex = (ushort)(Interlocked.Increment(ref GTAPacketSerializerHelper.msgIndex) & 0xFFFF);
            // Debug.Log("包索引:" + msgIndex + " " + packet.Id);
            if(IsAESEncrypt(packet))
            {
                var cryptoTransform = UMT.Framework.Security.EncryptAES.GetCryptoTransform();
                if (cryptoTransform == null)
                {
                    UnityEngine.Debug.LogError($"Send request failed, cryptoTransform is null, id: {packet.Id}");
                    return false;
                }
                
                byte[] source = new byte[packet.rawData.Length + CS_PACKAGE_HEAD_LENGTH];
                //填充内容
                Array.Copy(packet.rawData, 0, source, CS_PACKAGE_HEAD_LENGTH, packet.rawData.Length);
                //消息头
                Array.Copy(BitConverter.GetBytes(Converter.GetBigEndian((ushort)msgIndex)), 0, source, 0, 2);
                Array.Copy(BitConverter.GetBytes(Converter.GetBigEndian((ushort)packet.Id)), 0, source, 2, 2);
                Array.Copy(BitConverter.GetBytes(Converter.GetBigEndian((ushort)0)), 0, source, 4, 2); 
                byte[] encode = UMT.Framework.Security.EncryptAES.AESEncrypt(source);
                if (encode != null && encode.Length > 0)
                {
                    var encodeBytes = BitConverter.GetBytes(Converter.GetBigEndian((uint)encode.Length));// BitConverter.GetBytes(msgStrBytes.Length);
                    //发送加密的协议内容长度
                    m_SerializeCachedStream.Write(encodeBytes, 0, encodeBytes.Length);
                    //加密协议数据
                    m_SerializeCachedStream.Write(encode, 0, encode.Length);
                }
                else
                {
                    return false;
                }
            }
            else
            {
                //发送的协议内容长度
                m_SerializeCachedStream.Write(BitConverter.GetBytes(Converter.GetBigEndian((uint)(packet.rawData.Length + CS_PACKAGE_HEAD_LENGTH))),0,4);
                //发送的包索引
                m_SerializeCachedStream.Write(BitConverter.GetBytes(Converter.GetBigEndian((ushort)msgIndex)),0,2);
                //发送的协议ID
                m_SerializeCachedStream.Write(BitConverter.GetBytes(Converter.GetBigEndian((ushort)packet.Id)),0,2);
                //发送的协议ID与协议压缩前长度
                m_SerializeCachedStream.Write(BitConverter.GetBytes(Converter.GetBigEndian((ushort)0)),0,2);
                //协议数据
                m_SerializeCachedStream.Write(packet.rawData, 0, packet.rawData.Length);
                
            }
            BasicPacket.Release((BasicPacket)packet);
            int totalLength = (int)m_SerializeCachedStream.Position;
            m_SerializeCachedStream.SetLength(totalLength);
            m_SerializeCachedStream.WriteTo(destination);    //不会写入报错么？
            
#if UNITY_DEBUG
            UnityEngine.Debug.Log("----------Send data OK-------------");
#endif
            return true;
        }

        
        //单条消息不能超过8K
        private readonly MemoryStream m_SerializeCachedStream = new MemoryStream(1024 * 8);
        public bool SerializeContentHandler(IPacket packet, Stream destination)
        {
#if UNITY_DEBUG
            UnityEngine.Debug.Log("packet msgId:" + packet.msgId.ToString());
#endif
            // MARK:这段逻辑没看懂。。。
            // Debug.Log("有协议需要C#侧序列化为bytes");
            // MemoryStream memoryStream = null;
            // using (memoryStream = new MemoryStream())
            // {
            //     packet.rawData = (byte[])packet.message;
            // }
            packet.rawData = (byte[])packet.message;
            packet.message = null;
            return true;
        }

        public void ResetOnConnected(NetChannel channel, INetClient client, object data)
        {
            // msgIndex = 0;
        }
    }
}